﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Reflection;
using SQLPXBase.Factory.Keys;

namespace SQLPXBase.Factory
{
    public class ModelFactory<px>
        where px:Interfaces.ISQLProxyBase, new()
    {
        public ProxyManager<px> ProxyManager { get; private set; }

        public ModelFactory(ProxyManager<px> proxyManager)
        {
            ProxyManager = proxyManager;
        }

        public T New<T>()
            where T : FactorizableModel<px>
        {
            // Creazione di default senza parametri (solo factory)
            return (T) Activator.CreateInstance(typeof (T),
                                                BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public,
                                                null, new[] {this},
                                                CultureInfo.CurrentCulture);
        }

        public T New<T>(DataRow rw)
            where T : FactorizableModel<px>
        {
            if (rw == null) return null;

            T t = New<T>();
            t.InitializeFromDB(rw);
            return t;
        }

        public T New<T>(ModelCustomConstructor<T, px> constructorClass)
            where T : FactorizableModel<px>
        {
            return constructorClass.Construct(this);
        }

        public T Load<T>(PrimaryKey id)
            where T : FactorizableModel<px>
        {
            T t = New<T>();
            t.Load(id);

            return t;
        }

        public T LoadCustom<T>(IModelCustomLoader<T, px> loader)
            where T : FactorizableModel<px>
        {
            return New<T>(loader.Load(this));
        }

        public TColl List<TColl, TModel>(IModelCollectionLoader<TModel, px> loader)
            where TColl : IList<TModel>, new()
            where TModel : FactorizableModel<px>
        {
            DataTable dt = RawList<TColl, TModel>(loader);

            TColl t = new TColl();
            foreach (DataRow rw in dt.Rows)
                t.Add(New<TModel>(rw));

            return t;
        }

        public DataTable RawList<TColl, TModel>(IModelCollectionLoader<TModel, px> loader)
            where TColl : IList<TModel>, new()
            where TModel : FactorizableModel<px>
        {
            return loader.Load(this);
        }

        public void Delete<T>(ModelEraser<T, px> eraser)
            where T : FactorizableModel<px>
        {
            eraser.Delete(this);
        }
    }
}
